﻿using EventBus;
using LiteStep.Currencies;
using LiteStep.Events;
using LiteStep.Exchanges.BtcE;
using Newtonsoft.Json;
using RestSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LiteStep.DataSources.BtcE
{
	public class BtcERestApi2 : IDataSource
	{
		private RestClient restClient { get; set; }
		private IEventBus eventBus { get; set; }

		private bool running { get; set; }

		public BtcERestApi2(RestClient restClient, IEventBus eventBus)
		{
			LiteStep.Log.Debug("Creating BtcERestApi2");

			this.restClient = restClient;
			this.eventBus = eventBus;
			this.running = false;
		}

		~BtcERestApi2()
        {
			LiteStep.Log.Debug("Destroying BtcERestApi2");

            Stop();
        }

		public void Start(int seconds)
		{
			LiteStep.Log.Info("Starting BtcERestApi2");

			running = true;
			ContinuouslyPollTicker<Btc, Usd>(seconds);
			ContinuouslyPollTicker<Btc, Rur>(seconds);
			ContinuouslyPollTicker<Btc, Eur>(seconds);
			ContinuouslyPollTicker<Ltc, Btc>(seconds);
			ContinuouslyPollTicker<Ltc, Usd>(seconds);
			ContinuouslyPollTicker<Ltc, Rur>(seconds);
			ContinuouslyPollTicker<Nmc, Btc>(seconds);
			ContinuouslyPollTicker<Usd, Rur>(seconds);
			ContinuouslyPollTicker<Eur, Usd>(seconds);
			ContinuouslyPollTicker<Nvc, Btc>(seconds);
			ContinuouslyPollTicker<Trc, Btc>(seconds);
			ContinuouslyPollTicker<Ppc, Btc>(seconds);
			ContinuouslyPollTicker<Ftc, Btc>(seconds);
			ContinuouslyPollTicker<Cnc, Btc>(seconds);
		}

		public void Stop()
		{
			LiteStep.Log.Info("Stopping BtcERestApi2");

			running = false;
		}

		public async Task<Ticker<TFrom, TTo>> GetTickerAsync<TFrom, TTo>()
			where TFrom : ICurrency
			where TTo : ICurrency
		{
			TickerResponse<TFrom, TTo> tickerResponse = null;

			try
			{
				eventBus.FireEvent(new BeforeTickerRequestEvent<Ticker<TFrom, TTo>>());
				tickerResponse = await restClient.GetResponseAsync<TickerResponse<TFrom, TTo>>(
					new RestRequest(String.Format("{0}_{1}/ticker", typeof(TFrom).Name.ToLower(), typeof(TTo).Name.ToLower()), Method.GET));
			}
			finally
			{
				Ticker<TFrom, TTo> ticker = tickerResponse != null ?
					tickerResponse.Ticker : null;
				eventBus.FireEvent(new AfterTickerResponseEvent<Ticker<TFrom, TTo>>(ticker));
			}

			return tickerResponse != null ? tickerResponse.Ticker : null;
		}

		public async void ContinuouslyPollTicker<TFrom, TTo>(int seconds)
			where TFrom : ICurrency
			where TTo : ICurrency
		{
			while (running)
			{
				var ticker = await GetTickerAsync<TFrom, TTo>();
				await Task.Delay(seconds * 1000);
			}
		}

		public class RestClient : RestSharp.RestClient
		{
			public RestClient(string baseUrl)
				: base(baseUrl)
			{
			}

			public T GetResponse<T>(RestRequest request)
			{
				var response = Execute(request);
				if (response.Content.Contains("error"))
					throw new Exception("Response contained error: " + response.Content);
				return JsonConvert.DeserializeObject<T>(response.Content);
			}

			public Task<T> GetResponseAsync<T>(RestRequest request)
			{
				return Task.Factory.StartNew(() => GetResponse<T>(request));
			}
		}

		private class TickerResponse<TFrom, TTo>
			where TFrom : ICurrency
			where TTo : ICurrency
		{
			[JsonProperty(PropertyName = "ticker")]
			public Ticker<TFrom, TTo> Ticker { get; set; }
		}
	}
}
